﻿//package com.netcracker.taskmanager.XML;


//import com.netcracker.taskmanager.Task;
//import com.netcracker.taskmanager.exceptions.NoSuchEarliestTaskException;
package XML;
import Source.*;
//import exception.*;
import org.jdom2.DataConversionException;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DataXmlList extends LinkedList<Task> {
    private Task EarliestTask;
    private long lastID;
    private static final long LAST_ID=0;
    private String filePath;              //Путь к файлу;
    private List<Task> timeOutedTask;    //Список с просроченными Task
    private int countOfUnprocessedTask; //Текущее количество необработанных Task
    private int countOfTimeOutedTask;   //Количество просроченных Task ( генерируется при чтении XML),
                                        // не входит в количество необработанных

    //!открытие файла по умолчанию
    public DataXmlList(){
        super();
        try {
            openXML("list_of_task.xml");
        } catch (IOException | JDOMException ex) {
            this.filePath = "list_of_task.xml";
            setTimeOutedTask(new LinkedList());
            lastID = LAST_ID;
            countOfUnprocessedTask =0;
            countOfTimeOutedTask=0;
            EarliestTask=null;
        }
        
    }
    
    public DataXmlList(String filePath){
        super();
        this.filePath = filePath;
        setTimeOutedTask(new LinkedList());
        lastID = LAST_ID;
        countOfUnprocessedTask =0;
        countOfTimeOutedTask=0;
        EarliestTask=null;
    }
    public Task getEarliestTask(){
        if(isProcessedAll()) return null;
        return EarliestTask;
    }
    @Override
    public boolean add(Task task) {
        lastID++;
        task.setID(lastID);
        long timeTask = task.getDate().getTime();
        if((isEmpty())||((!isProcessedAll())&&(EarliestTask.getDate().getTime()>timeTask))){
            add(0,task);
            EarliestTask=task;
            countOfUnprocessedTask++; //!добавили новую задачу
            return true;}
        else{
            for (int i = 0; i < size(); i++) {
                if(super.get(i).getDate().getTime()>timeTask){
                    add(i,task);
                    countOfUnprocessedTask++; //!добавили новую задачу
                    return true;

                }
                if(i==(super.size()-1)){
                    add(size(),task);
                    countOfUnprocessedTask++; //!добавили новую задачу
                    return true;
                }
            }
        }

        return true;    //To change body of overridden methods use File | Settings | File Templates.
    }
    public void openXML(String filePath) throws IOException, JDOMException {
        setTimeOutedTask(new LinkedList()); //!если у нас уже есть файл и есть просроченные задачи
        Document document = (new SAXBuilder()).build(new FileReader(filePath));
        this.filePath = filePath;
        lastID = Long.parseLong(document.getRootElement().getAttribute("lastID").getValue());
        List<Element> buff = document.getRootElement().getChildren();
        super.clear();
        for (Element aBuff : buff) {
            Task bufTask = elementToTask(aBuff);
            if (!bufTask.isProcessed()){
                if(bufTask.getDate().getTime()<(new Date()).getTime()){
                    bufTask.setProcessed(true);
                    getTimeOutedTask().add(bufTask);
                    countOfTimeOutedTask++;
                }
                else{
                    countOfUnprocessedTask++;
                }
            }

            super.add(bufTask);
            if(countOfUnprocessedTask!=0)EarliestTask=get(0);

        }
    }
    public void save() throws IOException {
        saveAs(filePath);
    }
    public void saveAs(String fPath) throws IOException {
        Element buffRoot = new Element("Tasks");
        buffRoot.setAttribute("lastID", Long.toString(lastID));//!запись атрибута
        Document buffDoc = new Document(buffRoot);
        for (int i = 0; i < size(); i++) {
            buffRoot.addContent(taskToElement(get(i)));
        }
        XMLOutputter outputter = new XMLOutputter();
        outputter.setFormat(Format.getPrettyFormat());
        FileWriter fw = new FileWriter(fPath);
        outputter.output(buffDoc, System.out);
        outputter.output(buffDoc, fw);
        fw.flush();
        fw.close();
    }
    public boolean isProcessedAll(){
        checkEarliestTask();
        return countOfUnprocessedTask==0;
    }
    public boolean haveTimeoutedTask(){
        return countOfTimeOutedTask==0;
    }
    private static Element taskToElement(Task task){
        Element result = new Element("Task");
        result.setAttribute("id",""+task.getID());
        result.setAttribute("title",task.getTaskTitle());//!записываем имя задачи а не потока
        result.setAttribute("date",""+task.getDate().getTime());
        result.setAttribute("context",task.getContext());
        result.setAttribute("contacts",task.getContacts());
        result.setAttribute("processed",""+task.isProcessed());
        result.setAttribute("action",""+task.getAction());
        return result;
    }
    private static Task elementToTask(Element buff) throws DataConversionException {

        return new Task(Long.parseLong(buff.getAttribute("id").getValue()),buff.getAttribute("title").getValue(),
                buff.getAttribute("action").getValue(),buff.getAttribute("context").getValue(),buff.getAttribute("contacts").getValue(),
                new Date(Long.parseLong(buff.getAttribute("date").getValue())),buff.getAttribute("processed").getBooleanValue());
    }
    private void checkEarliestTask(){
        if(EarliestTask==null){
            for (int i = 0; i <size() ; i++) {
                if(!get(i).isProcessed()){
                    EarliestTask=get(i);
                    break;
                }
            }
            return;
        }
        if((EarliestTask!=null)&&(EarliestTask.isProcessed())){
            countOfUnprocessedTask--;
            if(countOfUnprocessedTask!=0){
                for (int i = 0; i <size() ; i++) {
                    if (!get(i).isProcessed()){
                        EarliestTask=get(i);
                        break;
                    }
                }
            }
        }
    }
    public List<Task> getTimeOutedTask() {
        return timeOutedTask;
    }
    public void setTimeOutedTask(List<Task> timeOutedTask) {
        this.timeOutedTask = timeOutedTask;
    }
}
